import multiply_sim::*;

module tb();

   logic [7:0] sig[15:0];
// = {8'h12, 8'h34};
   

   //logic [16:0][8:0] pps_16;
   pps_16x16_t pps_16;
   pps_8x8_t pps_8;
   pps_4x4_t pps_4;

   
   logic signed [31:0] tmp_result;
   
   initial
     begin
	    #10;
	    //test_print();

	begin : test_8x8_in_mix_mode
	   logic [7:0] a, b;
	   logic       sign, negate;
	   logic [16:0] correct_result;

	   sign = 1'b0;
	   negate = 1'b1;
	   
	   a = 8'h15;
	   b = 8'h24;
	   
	   pps_8 = gen_8x8_pps(
			       .i_a(a),
			       .i_b(b),
			       .i_sign(sign),
			       .i_negate(negate) );
	   
	   `print(pps_8.result);
	   // `print(pps_8.);
	   
	   for(int j=0;j<6;j++)
	     $display("rows_val[%d] = %x", j, pps_8.rows_val[j]);
	   
	end
	$finish;
	

	
	    // $display("size of sig : %d", sig.size());
		begin : test_8x8
		   logic [7:0] a, b;
		   logic 	   sign, negate;
		   logic [16:0] correct_result;


		   
		   $display("=============== 8x8 unsigned , not-negate mode ===============");
		   sign = 1'b0;
		   negate = 1'b0;
		   for(int i=0;i<=16'hffff;i++)
			 begin : verify_8x8
				a = i[7:0];
				b = i[15:8];
				correct_result = a * b;
				pps_8 = gen_8x8_pps(
									.i_a(a),
									.i_b(b),
									.i_sign(sign),
									.i_negate(negate) );
				if(pps_8.result != correct_result[15:0])
				  begin
					 $display("Failed");
					 $finish;
				  end
			 end // block: verify_8x8
		   $display("passed");

		   $display("=============== 8x8 signed , not-negate mode ===============");
		   sign = 1'b1;
		   negate = 1'b0;
		   for(int i=0;i<=16'hffff;i++)
			 begin : verify_8x8
				a = i[7:0];
				b = i[15:8];
				correct_result = $signed(a) * $signed(b);
				pps_8 = gen_8x8_pps(
									.i_a(a),
									.i_b(b),
									.i_sign(sign),
									.i_negate(negate) );
				if(pps_8.result != correct_result[15:0])
				  begin
					 $display("Failed");
					 $finish;
				  end
			 end // block: verify_8x8
		   $display("passed");

		   $display("=============== 8x8 unsigned , negate mode ===============");
		   sign = 1'b0;
		   negate = 1'b1;
		   for(int i=0;i<=16'hffff;i++)
		   // for(int i=0;i<=16;i++)
			 begin : verify_8x8
				a = i[7:0];
				b = i[15:8];
				// a = $random;
				// b = $random;
				correct_result = -(a * b);
				pps_8 = gen_8x8_pps(
									.i_a(a),
									.i_b(b),
									.i_sign(sign),
									.i_negate(negate) );
				
				// $display("-(%d * %d) = %d(%x)  <--> result=%x  ==> %s",
				// 		a, b, $signed(correct_result), correct_result,
				// 		pps_8.result, pps_8.result == correct_result[15:0] ? "equal" : "!!! Not Equal !!!");

				// for(int j=0;j<6;j++)
				//   $display("rows_val[%d] = %x", j, pps_8.rows_val[j]);
				// // break;
				
				if(pps_8.result != correct_result[15:0])
				  begin
					 $display("-(%d * %d) = %d(%x)  <--> result=%x  ==> %s",
							  a, b, $signed(correct_result), correct_result,
							  pps_8.result, pps_8.result == correct_result[15:0] ? "equal" : "!!! Not Equal !!!");
					 $finish;
				  end
			 end // block: verify_8x8
		   $display("passed");
		   
		   
		   $display("=============== 8x8 signed , negate mode ===============");
		   sign = 1'b1;
		   negate = 1'b1;
		   for(int i=0;i<=16'hffff;i++)
			 begin : verify_8x8
				a = i[7:0];
				b = i[15:8];
				correct_result = -($signed(a) * $signed(b));
				pps_8 = gen_8x8_pps(
									.i_a(a),
									.i_b(b),
									.i_sign(sign),
									.i_negate(negate) );
				
				// $display("-(%d * %d) = %d(%x)  <--> result=%x  ==> %s",
				// 		a, b, $signed(correct_result), correct_result,
				// 		pps_8.result, pps_8.result == correct_result[15:0] ? "equal" : "!!! Not Equal !!!");

				// for(int j=0;j<6;j++)
				//   $display("rows_val[%d] = %x", j, pps_8.rows_val[j]);
				// // break;
				
				if(pps_8.result != correct_result[15:0])
				  begin
					 $display("-(%d * %d) = %d(%x)  <--> result=%x  ==> %s",
							  $signed(a), $signed(b), $signed(correct_result), correct_result,
							  pps_8.result, pps_8.result == correct_result[15:0] ? "equal" : "!!! Not Equal !!!");
					 $finish;
				  end
			 end // block: verify_8x8
		   $display("passed");

		   $finish;
		   




		   
		   correct_result = -(a * b);
		   pps_8 = gen_8x8_pps(
							   .i_a(a),
							   .i_b(b),
							   .i_sign(sign),
							   .i_negate(negate) );


		   for(int i=0;i<5;i++)
			 $display("pps_8[%d] = %x", i, pps_8.pp[i]);
		   for(int i=0;i<5;i++)
			 $display("pps_8_S[%d] = %d, pps_8_E[%d] = %d", i, pps_8.S[i], i, pps_8.E[i]);
		   $display("result = %d (%x)", $signed(pps_8.result), pps_8.result);
		   
		   
		   $display("%d * %d = %d(%x)", a, b, correct_result, correct_result);
		

		end
		$finish;



	    
	pps_16 = gen_16x16_pps(
			       .i_a(16'habcd),
			       .i_b(16'h5678),
			       .i_sign(1'b1)
			       );
	
	tmp_result = $signed(16'habcd) * $signed(16'h5678);
	$display("multiply : %d * %d = %d (%x)", $signed(16'habcd), $signed(16'h5678), tmp_result, tmp_result);
	for(int i=0;i<9;i++)
	  $display("pps_16[%d] = %x", i, pps_16.pp[i]);
	for(int i=0;i<8;i++)
	  $display("pps_16_S[%d] = %d, pps_16_E[%d] = %d", i, pps_16.S[i], i, pps_16.E[i]);
	$display("result = %d (%x)", $signed(pps_16.result), pps_16.result);

	for(int i=0;i<32;i++)
	  $display("cols_sum[%d] = %d", i, pps_16.cols_sum[i]);
	

	// begin
	//    int r, res;
	//    for(int i=0;i<10000;i++)
	//      begin
	// 	r = $random();
	// 	pps_16 = gen_16x16_pps(
	// 			       .i_a(r[31:16]),
	// 			       .i_b(r[15:0]),
	// 			       .i_sign(1'b1)
	// 			       );
	// 	res = $signed(r[31:16]) * $signed(r[15:0]);
	// 	if(pps_16.result == res)
	// 	  $display("equal %d", i);
	// 	else
	// 	  break;
	//      end // for (int i=0;i<10000;i++)
	// end
	
	
	
		
     end

endmodule // tb
